#4.4python课
# txt='Neusoft'
# x=txt.center(20,"*")   #"*" 作用：填充空格
# print(x)
# txt='apple，apple '
# x=txt.count("apple")
# print(x)
#通过循环去求一个数的代码
# x=int(input("please input an integer") )
# ans=0
# iterLeft=x
# while iterLeft!=0:
#     ans=ans+x
#     iterLeft= iterLeft-1
# print(str(x)+"*"+str(x)+"="+str(ans) )
#问题answer；x是用户输入的数据不会受iterleft的影响。
#print后面的代码体现了如何用加法去实现乘法
#important point:设置while循环的的属性：1循坏外设迭代变量（iterleft）；
#                                    2需测试变量，确定是否完成；
#                                    3需改变循环内的变量，使它向终点0推进（iterLeft= iterLeft-1）
#
# 法1；从小到大
# n=int(input('请输入1一个数字：'))
# a=1
# sum=0
# while a<=n:
#     sum=sum+a
#     a+=1
# print(sum)
#法2：从大到小；
# n=int(input("please enter an itegar" )
# sum=0
# while n!=0:
#     sum=sum+n
#     n-=1
# print(sum)
#n=int(input('please enter an itegar'))
#a=1
#sum=0
#while n>=a:
#    sum=sum+n
#    a+=1
#print(sum)
#**重点** ↓是n=10时，对'1'的累加，即1累加了10次，结果是10
#问：如果我要累加100到0，修改什么，然后输入什么值即可-----------------------------------将+1改为+n，并且令n=100
# n=int(input ('please enter an interar'))
# sum=0
# while n!=0:
#     sum=sum+1
#     n-=1
# print(sum)
#for循环：
#for x in 'Nusoft':
#     print(x)
# sum=0
# for x in range(50,101):
#      sum=sum+x
#     # print(x)
# print(sum)


#while循环练习
# n=int(input("请输入一个数字："))
# sum=0
# while n!=0:
#     sum=sum+n
#     n-=1
# print(sum)
#法2：
#1先做循环终止条件的设置 i=1   用 sum去累加i值
# i=1
# sum=0
# while i<=100:
#     i+=1
#   sum=sum+i
#👆有错，i+=1与sum=sum+i的位置需要互换
#问题：sum对i进行累加，为啥不能把sum放在后面
#print(f'1-100的和累加等于：{sum}')
#
#while循环-猜数字案例
#import random
#num=random.randint(1,100)
#count=0
#Guess=True
#while Guess:
#    guess_num=int(input('输入你猜测的数字：'))
#    count+=1
#    if num==guess_num:
#        print("恭喜你，猜对了！")
#        flag=False
#    if  guess_num>num:
#      print("sorry,太大了请再猜一次")
#    if guess_num<num:
#      print('sorry,太小了，请再输入一次')
#print(f"你一共猜了{i}次")

#4.6python课
#The range()Function
#i=0
#for x in range(3,31,3):
#    i+=1
#    print(x)
#print(f"一共循环了{i}次
# for x in range(21001,21011)
#     print("NUIT"+str(x))
#listc列表            apple下标为0，banana为1   cherry为倒数第一个
#list1=["apple","banana","cherry"]
#print(list1[1])
#print(list1[-1])
# fruits =["apple","banana","cherry"]
# for x in fruits:
#     if x=="banana":
#         print(' red '+x)
#”in“的用法：    循环i，去代表s中的每一个字母
#s='python'
#for i in s:
#    print(i)
#'break'的用法
# list1=["apple","banana","cherry"]
# for x in list1:
#    if x=="banana":
#     print(x)
#       break
#“continue”-跳过 的作用   注意print 的位置：unreachable-不可到达
#fruits =["apple","banana","cherry"]
#a=0
#for x in fruits:
#  if x=="banana":
#     continue
#  a+=1   #注意a+=1的位置，对应的语句块   tab打出的空格比较工整 ，tab一次打四个空格
#         #错误:将continue 和a+=1对齐会导致其中的a+=1这一行被跳过，不被运行，所以打代码时要注意语句块之间的关系，多读才能找到错误
#  print(x)
#print(a)
#for else 循环语句
# for x in range(6):
#     if x ==3:break     #这个把for循环砍掉了，所以不会执行else
#     print(x)
# else:
#     print("For LooP finished!")
#“
# for x in range(6):
#     if x ==3:continue     #continue只是跳过当前变量”3“，其它还会继续运行
#     print(x)
# else:
#     print("For LooP finished!")
#***Nested Loop 循环嵌套      外层循环for走一次，内层走3次
# a=["red","big","tasty"]
# fruits =["apple","banana","cherry"]
# for x in a:
#    for y in fruits:
#        print(x,y)
#练习
#print(1)
#print(2)
# #
# print("1",end=" ")
# print('')
# print(2)
#
#print('1,1')
#print(end="2, ")
#print('2，2，2')

#for x in range(5):
#    for x in range (5):
#         print("* ")
#

# #
# for i in range(5):
#    for j in range(5):
#        print("* ",end=' ')
#    print(" ")

##print语句输出不换行功能：
#print("hello ")
#print("world")
##👇不换行输入
# print("hello",end="")
# print(' world')
#
# #对齐功能用\t去占空格
# print("hello\tworld")
# print("apple\tabanbanana")

#python 4.10 list用法  list是储存数据集合的4种内置函数之一 用：[]
#list1=['a',"b",'c']
#print(list1)
#ordered:有顺序的  changeable：可变的 值可重复
#changeable：可变的  例子↓
# a=1
# a=2
# 内存只有一个，且包含1，2两个值
# 如果是is则a=2会代替1
#list1=['a',"b",'c']
#print(list1[1])#第一项的索引index是0，即a→0
#print(list1[-1])
#**Range of indexes索引范围 eg
# list2=['a',"b",'c',"o","k","m","n"]
# print(list2[2:5])#左取右不取
# print(list2[:4])
# print(list2[2:])
# print(list2[-4:-1])
#*Check if item exists
# list1=['a',"b",'c']
# if "a"in list1:
#     print("yes,'apple'is in the fruit list")
#*change list items更改特定的项目值
# list1=['a',"b",'c']
# list1[1]="oo"
# print(list1)
# list1=['a',"b",'c',"o","k",'m']
# list1[1:3]=['aa',"bb",]
# print(list1)
#*insert items
# list1=['a',"b",'c']
# list1.insert(2,'watermelon')
# print(list1)     #outcome:['a', 'b', 'watermelon', 'c']

# #*Add list items  -- two ways
# #First: append("")进行附加   append增补 items
# list1=['a',"b",'c']
# list1.append('orange')
# print(list1)#结果：['a', 'b', 'c', 'orange']
# #Insert items
# list1.insert(1,"melon") #1是将melon加到第一个位置，即原来b的位置
# print(list1)#结果：['a', 'melon', 'b', 'c', 'orange']
# #***summary:区别：一个是追加，一个是插入。追加（append）从最后追加，插入（insert）可以随意

# #Extend list--扩展列表   用extend（）方法 其它列表追加到当前列表
# list1=['a',"b",'c']
# tropical=["m","p","y"]
# list1.extend(tropical)
# print(list1)

#Remove list items 去除列表--2 ways
# 1Remove specified item--  用remove（）  删除指定项
# 二、remove()
# 1、按照值来删除；
# 2、传递待删除元素，如果多个元素一样，默认删除第一个；
# 3、不会返回被删除的值
# list1=[1,3,6,7,8]
# list1.remove(3)
# print( list1)
# print (list1.remove(1) )#对列表元素进行搜索删除，而不是下表
# print( list1)
#结果：[1, 6, 7, 8]
#None                 👉说明不会返回被删除的值1
#[6, 7, 8]

# 2Remove specified index--  用pop（）  删除指定索引
# pop()
# 1、按位进行删除；
# 2、传递的是待删除元素的index；
# 3、会返回被删除的值。
# list1=["a","b","c"]
# list1.pop(0)
# print(list1)
# print(list1.pop(0))
#结果：['b', 'c']
# b                    👉说明会返回被删除的值b

#del keyword--删除关键字  👉方法：前＋del
# 可删除指定索引，也可删除整个列表 👇例子
# list=["a","b","c"]
# del  list[0]
# print(list)
#
# list1=["a","b","c"]
# del list1


# #clear the list--清除列表  👉方法；clear（） ！注意：列表仍存在，只是没有内容
# list1=["a","b","c"]
# list1.clear()
# print(list1)
#outcome；[]

# # For loop with list  嵌套循环
# fruit=["a","b","c"]
# color=["red"]
# for y in color:
#     for x in fruit:
#         if x=="b":
#             print(y, x)
#The break statement--暂停声明  👉用break
# fruit=["a","b","c"]
# for x in fruit:
#     print(x)
#     if x=="b":
#                 break
#  outcome:a
#          b
#
# fruit1=["a","b","c"]
# for x in fruit:
#     if x=="b":
#         break
#     print(x)
# outcome:a

# The continue statement--继续声明 👉用continue-跳过作用
# fruit1=["a","b","c"]
# for x in fruit1:
#     if x=="b":
#         continue
#     print(x)

# review exercises
# for x in range(5):
#     for y in range(5):
#       print("* ",end=" ") #对应内循环的for
#     print(" ")#对应外循环的for

#classess guess amd check 属于穷举法exhausted enumeration（作业中鸡的也是）
#ans→令他自增
#ans**3<x



#python 4.11 guess and check=exhaustive  enumeration穷举法  本质模拟人脑想法
#abs()
# print(abs(-1))绝对值函数
#cube root ：立方根
#integer：整数

# Code of Finding cube root of integer-利用代码找整数的立方根
# x=int(input('please enter a integer:'))
# num=0
# while num**3<x:#这里是如何猜测{generate guesses}
#     num+=1
# if num**3==x:#以下是我们如何检查是否得到了立方根
#     print("cube root of" +str(x)+"is"+str(num))
# else:
#     print(str(x)+"is not a perfect cube")
# point：The code only works for positive integers.👆

#负数 可以利用 abs()函数
# print(abs(-9))      outcome:9
# x=int(input("please enter a integer："))
# num=0
# while num**3<abs(x):
#     num+=1
# if num**3==abs(x) and x<0:
#     num=-num
#     print("cube root of" +str(abs(x))+"is"+str(num))
# else:
#     num=num
#     print("cube root of" +str(x)+"is"+str(num))
#loop characteristic循环特征：
#1.Need a loop variable-需要一个循环变量
#2.Initialize outside loop外面定义循环
#3.Changes within loop循环内部改变
#4.Test for termination depends on variable终止测试取决于变量
#5.Useful to think about a decrementing function考虑将程序变量集映射为整数的递减函数很有用
#6.Maps set of program variables into an integer当输入循环时，value是非负的当value <=0时，循环终止。
#7.When loop is entered, value is non-negative
#8.When value is <=0, loop terminates.
#9.The value is decreased every time through loop.

# Suppose we don’t initialize the variable
# Likely get a NameError. Or worse use an unexpected value to initialize the computation.
# 假设我们不初始化变量可能会出现名称错误。或者更糟的是，使用意外值来初始化计算。
#
# Suppose we don’t change the variable inside the loop?
# The program might end up with infinite loop, never reaching the terminating condition.
# 假设我们不改变循环中的变量？
# 程序可能会以无限循环结束，永远不会达到终止条件。

# Keep guessing until find the expected answer or guessed all values.
# The process is 👉exhaustive enumeration.
# 继续猜测，直到找到预期答案或猜到所有值。这个过程是穷尽列举。


#

#while 循环    while ans**3<x：
# x=int(input("please enter a integer："))
# num=0
# while num**3<abs(x):
#     num+=1
# if num**3==abs(x) and x<0:
#     num=-num
#     print("cube root of" +str(abs(x))+"is"+str(num))
# else:
#     num=num
#     print("cube root of" +str(x)+"is"+str(num))




# #用for循环去找整数的立方根
# x=int(input('please input a integer:'))
# for i in range (abs(x)+1):#因为左取右不取，所以要＋1，从而取到0到x的绝对值  注意num>=0
#     if i**3>=abs(x):   #想不明白为啥是大于等于
#         if x>0:
#             print(str(x)+"的立方根是"+str(i))
#         else:
#              print(str(x)+"的立方根是"+str(-i))
#         break


# x=int(input("请输入一个数字"))
# for i in range(x+1):
#     if i**3>=x:
#         print(i)
#         x=i
#         break

# x = int(input("请输入一个数字"))#question:
# for i in range(abs(x) + 1):#首先i是正数
#      if i ** 3 >=abs(x):
#         if x <0:#两种结果 所以用if语句 ，进行分情况讨论
#              print(-i)
#         else:
#             print(i)
#         # x = i/
#         break#对应的if语块
#
#
# x = 29
# epsilon = 0.01
# guess = 0.0
# increment = 0.01#步长
# num_guesses = 0#记录运行次数
# while abs(guess**3 - x) >= epsilon and guess**3<=x :#少了guess**3<=x会无限循环
#         guess += increment
#         print(guess) #print(结果对应的变量名称可以获得每一步的详细过程)
#         num_guesses += 1
# print('num_guess = ', num_guesses)#运行次数  穷举法
# if abs(guess** 3 - x) >= epsilon:
#     print("Failed on cube root of", x)
# else:
#     print(guess, " is close to the cube root of ", x)
#
# Binary search--二分法     Bin二进制的文件  square root平方根

# #python-4.17
# Binary search-二分法
# x = 25
# epsilon = 0.01
# num_guesses = 0#记录运行次数
# low=1.0
# high=x
# guess = (high+low)/2.0
# while abs(guess**2 - x) >= epsilon:
# print('low = '+str(low)+'high=')#运行次数  穷举法
# if abs(guess**2-x) >= epsilon:
#     print()
# else:
#     print(guess, " is close to the cube root of ", x)

#Tuple:元组-Ordered有序Unchangeable不可变元素Allow Duplicates可重复，通过（）定义  可通过下标访问index[0]
# tuple=("a","b","c")
# print(tuple)
# 注意只有一个元素时，要在元素后面加逗号，否则这是字符串而不是元组tuple。👇例子
# tuple1 = ("apple",)
# print(type(tuple1))
# #NOT a tuple
# tuple2 = ("apple")
# print(type(tuple2))

# t=tuple(("a","b","c"))#构造函数，将abc，用两个括号打包在一起变成tuple类型，只有一个（）只打包一个元素a
# print(t)
# 用下标去访问tuple里的内容
# tuple=("a","b","c")
# print(tuple[1])
#·元组是不可更改的，这意味着一旦创建了元组，就不能像list那样更改、添加或删除项
#“包装”元组-就是给它赋值。
#“拆包‘元组unpacking-加入元推
# fruits = ("apple","banana","cherry")
# (green, yellow, red) = fruits
# print(green)
# print(yellow)
# print(red)
# #元组有加法join，乘法multiply
# tuple1 = ("a","b","c")
# tuple2 = (1,2,3)
# tuple3 = tuple1 + tuple2
# print(tuple3)
# #元组有乘法👇
# fruits = ("apple","banana","cherry")
# tuple = fruits *2
# print(tuple)
#
# set:集合-元素具有unordered无序性，unchangeable互异性，unindexed.无索引index（）-符号{}
# Sets cannot have two items with the same value.
# Example:
# Duplicate values will be ignored重复着将被忽略👇:
# set1 = {"apple","banana","cherry","apple"}
# print(set1)
#set集合不能通过引用索引或键来访问集合中的项
# # 但可使用for循环loop遍历集合项，或者使用in关键字询问集合中是否存在指定的项
# set1 = {"apple","banana","cherry"}
# for x in set1:
#     print(x)
# # Check if "banana" is present in the set:
# set1 = {"apple","banana","cherry"}
# print("banana"in set1)

#python-4.18
# #Add Items-添加项目
# set1 = {"apple","banana","cherry"}
# # set1.add("orange")
# # print(set1)
# set1.update({"orange"})#加个大括号{}，放在小括号里面双引号外面就不会将orange分开
# print(set1)
# # #
# thisset = {"apple","banana","cherry"}
# tropical = {"pineapple","mango","papaya"}
# thisset.update(tropical)
# print(thisset)
# dictionary-元素不可重复，即键不可重复，新键会覆盖原值
# dict1 ={"brand":"Ford",
#         "model":"Mustang",#逗号勿漏
#         "year":1964,
#         "year":2022,
#         }
# print(dict1)
# # key-value；键值对  键不可重复，一个键可对应多个值
# dict1 ={"brand":"Ford",
#         "model":"Mustang",#逗号勿漏
#         "year":1964,
#         }
# print(dict1["brand"])
# print(dict1[0])#KeyError: 0错误原因没有0键，修改方法，把year改为0这个键就会输出1964
# ***#dictionary 中删除指定items的tip---👉用for循环＋del
myfamily = {
  "child1" : {
    "name" : "Emil",
    "year" : 2004
  },
  "child2" : {
    "name" : "Tobias",
    "year" : 2007
  },
  "child3" : {
    "name" : "Linus",
    "year" : 2011
  }
}
for x, y in myfamily.items():
    del x, y['year']
    print(y)

#Function函数  头＋体
# Abstraction-屏蔽细节，无需知道原理，只需要使用 black box
#Decomposition：分解-复杂东西简单化  将教务系统分成不同模块
#suppress details with abstraction -例如print不知源代码，直接实用
#1先定义2需要时再调用👉抄一遍再传参数-提升复用性
# def is_even(i):
#     """
#     :param i:
#     :return:
#     """
#     print("Inside is_even()")
#     return i%2==0
# # invoking a fun
# print(is_even(4))

# def add(a,b):
#     print(a+b)#只计算
#
# def add_re(a, b):
#     return (a+b)#有返回值-计算并保存
#
# x=add(1,2)
# y=add(1,2)
# print(x)
# print(y)

# def function(frame,lname):#frame叫做参数parameter
#     print(frame+" "+lname+' is a t')
# function("brian","z")#对应位置传参
# function("k","o")
# function("t","b")

#python 4.24
#❗**伪代码-----👉利于梳理思路--eg：tut2寻宝游戏
#tips：程序结构
#循环体外需定义一个 loop variable--chances
#while条件（通过玩家剩余的机会作为条件控制循环次数）：
#        循环体：
#         1.loop varible 需做出相应变化，以便控制循环次数
#         2.用户输入的数与答案做对比
#         有三种情况；
#                  小于
#                  等于
#                  或大

# Abstraction and Decomposition
#Function函数  头＋体
# Abstraction-屏蔽细节，无需知道原理，只需要使用 black box
#Decomposition：分解-复杂东西简单化  将教务系统分成不同模块

# Different types of functions in Python
# 1.Built - in functions内置函数
# eg：print(), input(), type() etc
# 2.User - defined functions自定义的函数
# eg：
#↙keyword ↓（even：func name）
# def is_even(i): #i：parameter：参数
#     """
#     :param i: a positive int    #param→Docstring文档字符串
#     :return : True if the param is even, otherwise, False.
#     """
#     print("Inside is_even()")#←Body函数体
#     return  i%2 == 0
# is_even(2) # Func call 调用函数
#
# # summary：
# # 函数的head头包括1keyword ，2func name ， 3parameter参数
# # 体：    print("Inside is_even()")#←Body函数体
# #         return  i%2 == 0
#
#
# a=int(input("Enter The First Number:"))
# b=int(input("Enter The Second Number:"))
# def calculate():
#  sum=a+b
#  print("The Sum is:",sum)
# calculate()

# #4.25
# # Variable Scope
# def func(x):#x为parameter
#     x = x + 1
#     print("in func(x) x = "+str(x))
#     return x
# x = 3
# z = func(x)#x为argument          函数

# def g(x):
#     def h():
#         x = "abc"
#     x = x+1
#     print("in g(x): x = ", x)
#     h()
#     return x
# x = 3
# z = g(x)
#
#
#
# def h(y) :
#     x =1
#     x = x + 1
# X=5
# h(x)
# print (x)

#Recursion递归--套娃
# 特征：一个函数在定义内调用自己
#1.base一定要有基态
#2.递归向出口前进

#合法递归
#
# def fact(n):
#     if n==0:
#         return 1
#     else:
#         return n * fact(n-1)
# x=fact(5)
# print(x)

# def num(j,i):
#     if i==1: #天数
#         return j
#     else:
#          return num(2*(j+1),i-1)#位置和变量一一对应
# print(num(1,10))
#
# def f(d,rest):
#     if d==1:
#         return rest
#     else:
#         return f(d-1,(rest+1)*2)
# print(f(10,1))
#
# i=0
# def move_tower(height,f_p,w_p,t_p):
#     if height>=1:
#         move_tower(height-1,f_p,t_p,w_p)
#         move_disk(f_p,t_p)
#
#         move_tower(height - 1, f_p, t_p, w_p)
# def move_disk(fp,tp):
#     print("moving disk from",fp,"to",tp)
#     global i
#     i+=1
#
# move_tower(3,"a","b","c")
# print(i)#完成移位的次数


#*星号作用：


#5.8 python8 下一章软件测试
# 测试用力 test case

# Defensive programe
# specificiations
# Modularize
# conditions
#
# Testing
# compare

# 静态语义错误print 不存在的东西
# eg
# print(hi)
# 由单元到整体测试
#
# 先随机测试，带几个数进去
#
# 测试方法包括两种：
# 1黑盒测试Black Box：不看代码设计的文字描述，可复用，需考虑边界条件
# 2白盒测试White（Glass） Box：除了看文字描述还要看代码，path-complete所有路径（工作）跑一遍
# 缺点：工作量大，复杂

# Debugging 调试运行键旁边的小虫子
# steep learning curve 不断尝试

# try:
#     a = int(input("give me a number: "))
#     b = int(input("give me another number: "))
#     print(a/b)
#     print("ok")
# except:
#     print("Bug in user input")#进行异常expection处理所以不会报错
# #     print("Outside")
#
# try:
#     a = int(input("give me a number: "))
#     b = int(input("give me another number: "))
#     print("a/b =",a/b)
#     print("a+b =",a+b)
# except:
#     print("Something wrong. Please check.")  # 其它错误
# except ZeroDivisionError :
#     print("we could not divide by .")
# except ValueError:
#     print("The input value cannot convert to number .")
# except:
#     print("Something wrong. Please check.")#其它错误
# print("Outside")#顶格写
#except语句块不能调换位置，因为语句块包含关系不同
# try和else连用出错跳到expect，无论是否出错，finally都会执行

# # ↓死循环，break打断
# while True:
#     try:
#         n = input("please input an integer: ")
#         n = int(n)
#         break
#     except ValueError:
#         print("Input not an integer; try again")
# print("Correct input of an integer .")
# #用try 和except规范用户输入

# data = []
# # file_name = input("provide a name of a file of data ")
# file_name = "C:\\Users\\86178\\PycharmProjects\\pythonProject\\python 2023 last term\\IN3306.txt"
# try:
#     f = open(file_name, 'r')
# except IOError:
#     print('cannot open', file_name)
# else:
#     for new in f:#f只读不改变
#         # print(new)
#         if new != '\n':#判断是否有斜杆n，为保证读取时不会把空格看成学生名，所以要判断一下
#            addIt = new[:-1].split(',') # remove  trailing去掉斜杠n，利用左取右不取，split分开，addIt加入小列表
#            new_addIt=[]
#            for item in addIt:
#                new_addIt.append(item.strip())
#            # print(new_addIt)
#            data.append(addIt)
# finally:
#     f.close() # close file even if fail拿数据后关门
# # print(data)
# # print(f)
#
# gradeData = []
# if data:
#     for student in data:
#         try:
#              print(student)
#              gradeData.append([student[0:-1],[student[-1]]])
#              print([student[0:-1],[student[-1]]])
#              print("======================")
#         except IndexError:
#             gradeData.append([student[0:-1],[]])
# # Append this block to the end of the last block.
#
# f = open(file_name, 'w')
# f.write("Ling, Gu, 100")
# f.close()

#exception controlling input
# def get_rations(L1,L2):
#     """
#
#     :param L1:
#     :param L2:
#     :return:
#     """
#     ratios=[]
#     for index in range (len(L1)):
#        try:
#         ratios.append(L1[index]/float(L2[index]))
#         except ZeroDivisionError:
#         ratios.append(float("Nan"))
#         except:
#         raise ValueError("get ratios called with bad arg(参数)")
#  return ratios
# #raise ：抛出异常，为了更好的控制程序运行

# test=[[["p",'k'],[80.0,70.0,85.0]],
#       [["b","w"],[100.0,80.0,74.01]]],
# print(test[0][1])

# test=[[["p",'k'],[80.0,70.0,85.0]],
#       [["b","w"],[100.0,80.0,74.01]]],
#
# test_grades = [[['peter', 'parker'], [80.0,70.0,85.0]],
#                [['bruce',"wayne"],[100.0,80.0,74.01]],
#       [['tony',"stuck"],[100.,90.0, 90.0]],
#                    [[ 'deadpool'],[]]],
#
#
# def get_stats(class_list):
#       new_stats=[]
#       for elt in class_list:
#             new_stats.append([elt[0],elt[1],elt[]])
#Assertion；防御性编程，判断向下运行的情况，检查函数输入，输出，可以快速定位bug

#Classes and Objects；面向对象编程Object-oriented,
#Classes：类是蓝图，❗由属性properties和行为methods为组成，
# 👆学习目的：想自己创造用户自己自定义的类
#Objects=instance是蓝图的具体化:对象，字符串，字典，列表，浮点数；可以用del删除
#有type，data representition属性，for interaction，

# 列表的内部结构：Linked list链表：一节数据一节地址   优点：有效利用碎片化空间
#
# 数组：放在连续的空间，所以链表可以提高空间利用率
#black box ：把细节隐藏

# # 定义类的：attribute属性，name姓名，behaviour行为
# class Coordinate(object):#coordinate坐标，协调
#     # #object；一切的基类，任意一个都可inherit继承它，他是父类
#     # coordinate；他是子类
#     """
#     define attributes here。
#     """
# # ❗必考self永远指向当前实例化本身
# class Coordinate(object):
#     def __init__(self,x,y):#self指的是实例化对象a，other指的是b
#         self.x=x
#         self.y=y
# #👆定义属性
#     def distance(self,other):
#         x_diff=(self.x-other.x)**2
#         y_diff=(self.y-other.y)**2
#         return(x_diff+y_diff)**0.5
#类的实例化过程
# a=Coordinate(0,0)
# b=Coordinate(3,4)
# print(a.x)
# print(a.y)
# print(a.distance(b))#self指的是实例化对象a，other指的是b
# # “.’：用于访问实例化对象

# class Person(object):
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
# P1=Person("j",18)
# print(P1.name)
# print(P1.age)
# class Person(object):
#     def __init__(self,age,name):
#         self.age=age
#         self.name=name
#     def eating(self,food):
#         print(self.name+" is eating "+food)
#     def sleep(self):
#         print(self.name + "is sleeping" )
#
#     def chat(self,friend):
#         print(self.name + " is chating with "+friend)
# P1=Person(18,"j")
# P1.sleep()
# print(P1.age)
# print(P1.name)
# P1.eating('banana')
# P1.chat('k')
#
#
# class student:
#     name=None
#     def say_hi(self):
#
#
# class ShoppingList:
#     products = []
#     def __init__(self):
#         print('Shopping list created')
#     def add(self, name):
#         self.products.append(name)
#     def show(self):
#         print(self.products)
# groceries = ShoppingList()
# groceries.add('Peanutbutter')
# groceries.add('Milk')
# groceries.show()

# class Coordinate(object):
#     def __init__(self, x, y):
#         self.x = x
#         self.y = y
#         def distance(self, other):
#             x_diff = (self.x - other.x)
#             y_diff = (self.y - other.y)
#             return (x_diff + y_diff)
# def __add__(self):
#     a=Coordinate(3,4)
#     b=Coordinate(1,2)


#
# class Animal(object):
#     def __init__(self, age):
#         self.age = age
#         self.name = None
#     def get_age(self):
#         return self.age
#     def get_name(self):
#         return self.name
#     def set_age(self, new_age):
#         self.age = new_age
#     def set_name(self, new_name):
#         self.name = new_name
#     def speak(self):
#         print("xxxxxx")
#
#
# class cat(Animal):
#     def speak(self):
#         print("meow~")
#     def chasing_mouse(self):
#         print(self.name+" is chasing a mouse.")
# Tom = cat(2)
# Tom.set_name('Tom')
# Tom.speak()
# print(Tom.get_name())
#
#
#
# # 一个子类要完整调用它的父类在子类初始化函数一定要调用它的父类
#
# class Animal(object):
#     def __init__(self, age):
#         self.age = age
#         self.name = None
#     def get_age(self):
#         return self.age
#     def get_name(self):
#         return self.name
#     def set_age(self, new_age):
#         self.age = new_age
#     def set_name(self, new_name):
#         self.name = new_name
#     def speak(self):
#         print("xxxxxx")
#
#
# class dog(Animal):
#     def speak(self):
#         print("旺~")
#     def chasing_mouse(self):
#         print(self.name+" is chasing a mouse.")
# Tom = dog(2)
# Tom.set_name('Tom')
# Tom.speak()
# print(Tom.get_name())



# Polymorphism多态；同一函数名，在传入不同参数时有不同结果
#
# 如果子类有其它属性与父类不同才要另外进行函数初始化

# Inheritance：
# 继承


# Encapsulation
# 封装
#
# class China():
#     def capital(self):
#         print("Beijing is the capital of China.")
#     def language(self):
#         print("Chinese is the most widely spoken language of China.")
#     def type(self):
#         print("China is a developing country.")
# class USA():
#     def capital(self):
#         print("Washington, D.C. is the capital of USA.")
#     def language(self):
#         print("English is the primary language of USA.")
#     def type(self):
#         print("USA is a developed country.")
# obj_chn = China()
# obj_usa = USA()
# for country in (obj_chn, obj_usa):#通过创建元组去访问
#     country.capital()
#     country.language()
#     country.type()





















# # instance实例变量，属于莫一个单独的实例化变量
# import datetime#引入模块
# class Person(object):#
#     def __init__(self, name):
#         self.name = name
#         self.birthday = None    #   👇以空格分割的意思
#         self.lastname = name.split(' ')[-1]#last name 姓氏从名字里分割
#     def __str__(self):#规范输出，名字而不是地址
#         return self.name
#
#     #通过年龄进行排列,如何比较身高，成绩等
#     def __lt__(self, other):#lt：less than 小于
#         if self.getAge ()== other.getAge():
#             print("same age")
#             return False
#
#         return self.birthday < other.birthday
#
#
#     # def __lt__(self, other):#lt：less than 小于
#     #     if self.lastname == other.lastname:
#     #         return self.name < other.name#对比名字
#     #     return self.lastname < other.lastname
#     def getLastName(self):
#         return self.lastname
#     def setBirthday(self,year,month,day):
#         self.birthday = datetime.date(year,month,day)#调用引入参数
#     def getAge(self):
#         if self.birthday == None:
#             raise ValueError
#         return int((datetime.date.today() - self.birthday).days / 365)
# #               ↑取整数            👆从系统调用日历-------------活着的天数÷365
# # p1=Person("glllllllllllllllll")
# # p2=Person("tttttttttttttth")
# # p1.setBirthday(1996,1,1)
# # p2.setBirthday(2003,3,8)
# # print(p1.getAge())
# # print(p2.getAge())
# # #int向下取整
# # print(datetime.date.today())
# # print(type(p1.birthday))#输出为日期类型可以直接进行加减运算
#
# # print(p1<p2)
# # print("ming xiao"<"fang xiao")#为什么字符串之间可以进行比较
# # #字符串比较不看长度看字母的排序，m排比较后所以大于f
# # print(ord("f"))#f的内置值
# # # 姓氏相同时再看名字，先看后面的姓再看前面名字的字母的排列
#
# p1 = Person("Ming Xiao")
# p1.setBirthday(1996,11,5)
# p2 = Person("Fang Xiao")
# p2.setBirthday(2000,12,15)
# p3 = Person("Jie A")
# p3.setBirthday(1998,5,20)
# personList = [p1,p2,p3]
# for p in personList:
#     print(p)
#     personList.sort()
# print("=======================After sort. =======================")
# for p in personList:
#     print(p)
# #sort函数从小到大排
#---------------------------------------------------------------------------
# instance实例变量，属于莫一个单独的实例化变量
# import datetime#引入模块
# class Person(object):#
#     def __init__(self, name):
#         self.name = name
#         self.birthday = None
#         self.lastname = name.split(' ')[-1]#last name 姓氏从名字里分割
#     def __str__(self):#规范输出，名字而不是地址
#         return self.name
#
#
#
#
#
#     def __lt__(self, other):#lt：less than 小于
#         if self.lastname == other.lastname:
#             return self.name < other.name#对比名字
#         return self.lastname < other.lastname
#     def getLastName(self):
#         return self.lastname
#     def setBirthday(self,year,month,day):
#         self.birthday = datetime.date(year,month,day)#调用引入参数
#     def getAge(self):
#         if self.birthday == None:
#             raise ValueError
#         return int((datetime.date.today() - self.birthday).days / 365)
# #               ↑取整数            👆从系统调用日历-------------活着的天数÷365
# p1=Person("glllllllllllllllll")
# p2=Person("tttttttttttttth")
# p1.setBirthday(1996,1,1)
# p2.setBirthday(2003,3,8)
# print(p1.getAge())
# print(p2.getAge())
# NeuPerson继承class Person
# #题目：Definition of NeuPerson. It's the child class of Person
#Please define a class named NeuPerson,
# It inherits fromcass person.
# For each student, it has a unique student id such as“oo1” ”oo2”...."o10”,
# You need to define a getStuid( )method to
# return the id of the instance.
# For each student, it has major,
# When we try to print aninstance of Neuperson,👉表示补充新属性major

# The ouput should be;
# 001Kendrick:SE

# # #规范化输出
# class NeuPerson(Person):#调用父类person的初始化函数进行继承，他父类的属性
# # This is a variable shared between Instance of NeuPerson.
#     nextId = 0#类内共享变量--class variable
#     def __init__(self,name):#,major):
#         Person.__init__(self, name,)#子类调用父类继承父类Person的属性
#         self.id = NeuPerson.nextId#因为nextId是类内变量，所以要用类.nextId调用
#         # self.major=major
#         #super（）__init__(name)👆
#         NeuPerson.nextId += 1#访问类内变量后，赋值自增1
#
#     def getIdnum(self):#取得ID的数字
#         return self.id
#     def __lt__(self, other):#less than函数
#         return self.id < other.id#进行id之间的整数运算
#     def speak(self, sentence):
#         return (self.getLastName() + " says: " + sentence)
#     def __str__(self):
#        return str(self.id).zfill(3)+self.lastname
#
#
#     def getStuid(self):
#         return str(self.id).zfill(3)
# #sentence是参数，用户传进来
#
# np1=NeuPerson("jianbin ou")
# np2=NeuPerson("Bruce wayne")
# np3=NeuPerson('be')
# print(np1.getIdnum())
# print(np2.getIdnum())
# print(np3.getIdnum())
# # 谁在前就调用谁的lt运算规则
# print(np1>p1)
# print(p1<np1)


# print(ord("林"))
# print(ord("🐖"))#ord用于找内置编码
#排序基于less than函数的内容类型
# stu list - [np3, np2, np1]
# for stu in stu list:
# print(stu, stu.getstuid())stu list.sort()-=After softeprint('for stu in stu list:print(stu, stu.getStuid())
#


# 对于任意两个实例化对象来说，摆在左边那位会调用对应的魔法运算去进行实例化
# 谁在前就调用谁的运算规则

# # 学生类
# class Student(NeuPerson):
#     pass
# #  本科生类
# class UG(NeuPerson):
#     def __init__(self,name,classYear):
#         NeuPerson.__init__ (self,name)#调用父类NeuPerson的函数
#         self.year = classYear
#     def getclass(self):
#         return self.year
#     def speak(self,utterance):
#         return NeuPerson.speak(self,"Doude"+utterance)
# class PG(NeuPerson):#写法的作用：PG会调用父类NeuPerson的函数
#     pass#未写任何东西，继承了NeuPerson的属性
# class TS(NeuPerson):
#     pass
# def isstudent(obj):
#     return isinstance(obj, UG) or isinstance(obj, PG) or isinstance(obj,TS)
#                         # 👆本科生类                👆研究生生类            👆转校生生生类

# #通用型把所有类的全部改为Student类进行细化它们的学历
# #学生类
# class Student(NeuPerson):
#     pass
# #本科生类
# class UG(Student):
#     def __init__(self,name,classYear):
#         NeuPerson.__init__ (self,name)#调用父类NeuPerson的函数
#         self.year = classYear
#     def getclass(self):
#         return self.year
#     def speak(self,utterance):
#         return NeuPerson.speak(self,"Doude"+utterance)
#
# class Grade(object):
#     def __init__(self):
#         self.students=[]#空列表
#         self.grades={}
#         self.isSorted=True
#
#     def addStudent(self,student):#把student传入
#         if student in self.students:
#             raise ValueError("D S")
#         self.students.append(student)
#         self.grades[student.getIdnum()]=[]
#         self.isSorted=False#防止打乱数据
#     def addGrade(self,student,grade):
#         try:
#             self.grades[student.getIdnum()].append(grade)
#         except KeyError:
#             raise ValueError("S IS NOT IN  G")
#
#     def getGrades(self,student):
#         try:
#             return self.grades[student.getIdnum()][:]#[:]表示可以取得列表所有的值
#         except KeyError:
#             raise ValueError("s is not in Gradebook")
#     def allStudents(self):
#         if not self.isSorted:
#             self.students.sort()
#             self.isSorted=True
#         return self.students[:]#学生打包成列表返回列表
#
# def gradeReport(course):
#     report=[]
#     for s in course.allStudents():
#         tot=0.0
#         numGrades=0
#         for g in course.getGrades(s):
#             tot+=g
#             numGrades+=1
#         try:
#             average=tot/numGrades
#             report.append(str(s)+"\"s mean grade is "+str(average))
#         except ZeroDivisionError:
#             report.append(str(s)+"has no grades")
#     return"\n".join(report)
# ug1=UG("MD",2018)
# ug2=UG("BA",2019)
# ug3=UG("DH",2017)
# ug4=UG("MZ",2017)
# pg1=PG("BG")
# pg2=PG("SW")
# six00=Grade()
# six00.addStudent(pg1)
# six00.addStudent(ug2)
# six00.addStudent(ug1)
# six00.addStudent(pg2)
# six00.addStudent(ug4)
# six00.addStudent(ug3)
# print(gradeReport(six00))
#封装👆
